﻿module;

#include <map>
#include <boost/tuple/tuple.hpp>
#include <boost/utility.hpp>
#include <boost/unordered_map.hpp>
#include <boost/any.hpp>
#include <type_traits>


//export module message_bus;
export module fast_utils:message_bus;

export  namespace fast::util{
/// @note 前向声明
    template<typename... Args>
    struct Impl;

/// @note 基本定义
    template<typename First, typename... Args>
    struct Impl<First, Args...> {
        /// @note 消息类型名字：融合了参数名字的字符串
        static std::string name() {
            return std::string(typeid(First).name()) + " " + Impl<Args...>::name();
        }
    };

/// @note 递归终止
    template<>
    struct Impl<> {
        static std::string name() {
            return "";
        }
    };

/// @note 返回该类型名字
    template<typename... Args>
    std::string type_name() {
        return Impl<Args...>::name();
    }

    template<typename R = void>
    class MessageBus : boost::noncopyable {
    public:
        // 注册

        /// @note 非成员函数
        template<class... Args, class F, class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type>
        void Attach(const std::string &strKey, F &&f) {
            std::function < R(Args...) > fn = [&](Args... args) { return f(std::forward<Args>(args)...); };
            m_map.insert(std::make_pair(strKey + type_name<Args...>(), std::move(fn)));
        }

        /// @note 非 const 成员函数 —— R (C::*f)(DArgs...)
        template<class... Args, class C, class... DArgs, class P>
        void Attach(const std::string &strKey, R (C::*f)(DArgs...), P &&p) {
            std::function < R(Args...) > fn = [&, f](Args... args) { return (*p.*f)(std::forward<Args>(args)...); };
            m_map.insert(std::make_pair(strKey + type_name<Args...>(), std::move(fn)));
        }

        /// @note const 成员函数 —— R (C::*f)(DArgs...) const
        template<class... Args, class C, class... DArgs, class P>
        void Attach(const std::string &strKey, R (C::*f)(DArgs...) const, P &&p) {
            std::function < R(Args...) > fn = [&, f](Args... args) { return (*p.*f)(std::forward<Args>(args)...); };
            m_map.insert(std::make_pair(strKey + type_name<Args...>(), std::move(fn)));
        }

        // @note 广播消息，主题和参数可以确定一个消息, 所有的消息接收者都将收到并处理该消息
        template<typename... Args>
        void SendReq(const std::string &strTopic, Args... args) {
            auto range = m_map.equal_range(strTopic + type_name<Args...>());
            for (auto it = range.first; it != range.second; it++) {
                std::function < R(Args...) > f = boost::any_cast<std::function<R(Args...)>>(it->second);
                f(args...);
            }
        }

#ifdef WIN32

        // @note 移除消息
        template<typename... Args>
        void Remove(const std::string &strTopic) {
            std::string strMsgType = type_name<Args...>();
            auto range = m_map.equal_range(strTopic + strMsgType);
            m_map.erase(range.first, range.second);
        }

#endif
    private:
        std::multimap<std::string, boost::any> m_map;

    };
}